import {BrowserWindow, dialog, ipcMain, Menu, clipboard, shell} from 'electron'
import {settingsDB} from "../database/settings";
import fileSpace, {initFileSpace} from "../files";
import {UserSettings} from "@/types";
import {DirectoryTreeNode, TreeWalkOptions} from "../../filespace/src";
import {join} from "path";
import './menuHandlers'

// 初始化相关
ipcMain.handle('ready:settings', async () => {
  try {
    // 初始化设置数据库
    await settingsDB.init()
  } catch (error) {
    console.error('Failed to load editor store...', error)
    throw error
  }
})
ipcMain.handle('ready:fileSpace', async () => {
  try {
    const notebookPath = await settingsDB.getSettings(['editor', 'notebookPath']);
    if (!notebookPath) {
      throw new Error('No notebook path found')
    }
    return initFileSpace(notebookPath)
  } catch (error) {
    console.error('Failed to load fileSpace store...', error)
    throw error
  }
})

// 设置相关
ipcMain.handle('settings:load', async () => {
  try {
    const settings = await settingsDB.getSettings();
    if (!settings) {
      throw new Error('No settings found')
    }
    // 确保返回的数据可以被序列化
    return JSON.parse(JSON.stringify(settings)) as UserSettings
  } catch (error) {
    console.error('Failed to load settings:', error)
    throw error
  }
})
ipcMain.handle('settings:save', async (_, settings: Partial<UserSettings>) => {
  try {
    // 确保接收的数据是纯对象
    const cleanSettings = JSON.parse(JSON.stringify(settings))
    await settingsDB.updateSettings(cleanSettings)
  } catch (error) {
    console.error('Failed to save settings:', error)
    throw error
  }
})

// 文件相关
ipcMain.handle('files:history:get', async (_, fileId: string) => {
  try {
    const res = await fileSpace?.getFileHistory(fileId)
    return res?.data ?? []
  } catch (error) {
    console.error('Failed to get histories:', error)
    throw error
  }
})
ipcMain.handle('files:selectPath', async () => {
  const result = await dialog.showOpenDialog({
    title: '选择文件空间地址',
    properties: ['openDirectory']
  })

  if (!result.canceled && result.filePaths.length > 0) {
    return result.filePaths[0]
  }
  return null
})
ipcMain.handle('files:create', async (_, name: string, content?: string, parentId?: string) => {
  try {
    return await fileSpace?.createFile(name, content, parentId)
  } catch (error) {
    console.error('Failed to create file:', error)
    throw error
  }
})
ipcMain.handle('files:load', async (_, fileId: string) => {
  try {
    const res = await fileSpace?.getFileContent(fileId)
    return res?.data ?? ''
  } catch (error) {
    console.error('Failed to get file content:', error)
    throw error
  }
})
ipcMain.handle('files:save', async (_, fileId: string, content: string) => {
  try {
    const res = await fileSpace?.saveFileContent(fileId, content)
    return res?.success ?? false
  } catch (error) {
    console.error('Failed to save file:', error)
    throw error
  }
})
ipcMain.handle('files:delete', async (_, fileId: string) => {
  try {
    const res = await fileSpace?.delete(fileId)
    return res?.success ?? false
  } catch (error) {
    console.error('Failed to delete file:', error)
    throw error
  }
})
ipcMain.handle('files:move', async (_, fileId: string, parentId?: string) => {
  try {
    const res = await fileSpace?.move(fileId, parentId)
    return res?.success ?? false
  } catch (error) {
    console.error('Failed to move file:', error)
    throw error
  }
})
ipcMain.handle('files:addOrRemoveOpen', async (_, fileId: string) => {
  try {
    const res = await fileSpace?.addOrRemoveOpenedFile(fileId)
    return res?.success ?? false
  } catch (error) {
    console.error('Failed to open file:', error)
  }
})
ipcMain.handle('files:openeds', async () => {
  try {
    const res = fileSpace?.getOpenedFiles()
    return res || []
  } catch (error) {
    console.error('Failed to get opened files:', error)
    throw error
  }
})

// 文件夹相关
ipcMain.handle('dirs:create', async (_, name: string, parentId?: string) => {
  try {
    return await fileSpace?.createDirectory(name, parentId)
  } catch (error) {
    console.error('Failed to create dir:', error)
    throw error
  }
})
ipcMain.handle('dirs:delete', async (_, dirId: string) => {
  try {
    const res = await fileSpace?.delete(dirId)
    return res?.success ?? false
  } catch (error) {
    console.error('Failed to delete dir:', error)
    throw error
  }
})
ipcMain.handle('dirs:move', async (_, dirId: string, parentId?: string) => {
  try {
    const res = await fileSpace?.move(dirId, parentId)
    return res?.success ?? false
  } catch (error) {
    console.error('Failed to move dir:', error)
    throw error
  }
})
ipcMain.handle('dirs:childs', async (_, dirId: string) => {
  try {
    const res = await fileSpace?.getDirectoryContents(dirId)
    if (!res || !res.success) {
      return []
    }
    return res.data
  } catch (error) {
    console.error('Failed to get dir content:', error)
    throw error
  }
})
ipcMain.handle('dirs:root', async () => {
  try {
    const res = await fileSpace?.getRootDirectory()
    return res?.data ?? null
  } catch (error) {
    console.error('Failed to get root items:', error)
    throw error
  }
})
ipcMain.handle('dirs:build', async (_, startPath?: string, options?: TreeWalkOptions) => {
  try {
    const res = await fileSpace?.buildDirectoryTree(startPath, options)
    return res?.data ?? null
  } catch (error) {
    console.error('Failed to build file tree:', error)
    throw error
  }
})
ipcMain.handle('dirs:tree', async () => {
  try {
    const res = await fileSpace?.getDirectoryTrees()
    return res?.data ?? []
  } catch (error) {
    console.error('Failed to get file tree:', error)
    throw error
  }
})
ipcMain.handle('dirs:tree-lazy', async (_, directoryId: string) => {
  try {
    const res = await fileSpace?.lazyLoadDirectoryTrees(directoryId)
    return res?.data ?? []
  } catch (error) {
    console.error('Failed to lazy load file tree:', error)
    throw error
  }
})
ipcMain.handle('dirs:openedIds', async () => {
  try {
    const res = fileSpace?.getOpenedDirectoryIds()
    return res || []
  } catch (error) {
    console.error('Failed to get opened directories:', error)
    throw error
  }
})

// 临时文件相关
ipcMain.handle('temps:create', async (_, name: string, parentId?: string, content?: string) => {
  try {
    const res = await fileSpace?.createTempFile(name, parentId, content)
    if (!res || !res.success) {
      return null
    }
    return res.data
  } catch (error) {
    console.error('Failed to create temp file:', error)
    throw error
  }
})
ipcMain.handle('temps:load', async (_, fileId: string) => {
  try {
    const res = await fileSpace?.getTempFileContent(fileId)
    return res?.data ?? ''
  } catch (error) {
    console.error('Failed to get temp file content:', error)
    throw error
  }
})
ipcMain.handle('temps:save', async (_, fileId: string, content: string) => {
  try {
    const res = await fileSpace?.updateTempFile(fileId, content)
    return res?.success ?? false
  } catch (error) {
    console.error('Failed to save temp file:', error)
    throw error
  }
})
ipcMain.handle('temps:delete', async (_, fileId: string) => {
  try {
    const res = await fileSpace?.deleteTempFile(fileId)
    return res?.success ?? false
  } catch (error) {
    console.error('Failed to delete temp file:', error)
    throw error
  }
})
ipcMain.handle('temps:all', async () => {
  try {
    const res = await fileSpace?.getUnsavedFiles()
    return res?.data ?? []
  } catch (error) {
    console.error('Failed to get temp files:', error)
    throw error
  }
})

// 上下文菜单相关（添加新的快捷菜单需要在types/electron.d.ts中添加命令类型）
ipcMain.handle('contextmenus:common', async (event) => {
  const menu = Menu.buildFromTemplate([
    {
      label: '关于',
      click: () => {
        event.sender.send('context-menu-command', 'about')
      }
    }
  ])
  menu.popup({window: BrowserWindow.fromWebContents(event.sender) as BrowserWindow})
})
ipcMain.handle('contextmenus:note:dirs', async (event, item: DirectoryTreeNode) => {
  const itemData = JSON.parse(JSON.stringify(item)) as DirectoryTreeNode
  const notebookPath = await settingsDB.getSettings(['editor', 'notebookPath'])
  const menu = Menu.buildFromTemplate([
    {
      label: '新建文件夹',
      click: () => {
        event.sender.send('contextmenus:note:dirs', 'new-dir', itemData)
      }
    },
    {
      label: '新建笔记',
      click: () => {
        event.sender.send('contextmenus:note:dirs', 'new-note', itemData)
      }
    },
    {type: 'separator'},
    {
      label: '打开文件所在位置',
      click: () => {
        shell.showItemInFolder(join(notebookPath, itemData.item.relativePath))
      }
    },
    {type: 'separator'},
    {
      label: '复制',
      accelerator: 'CmdOrCtrl+C',
      click: () => {
        event.sender.send('contextmenus:note:dirs', 'copy', itemData)
      }
    },
    {
      label: '剪切',
      accelerator: 'CmdOrCtrl+X',
      click: () => {
        event.sender.send('contextmenus:note:dirs', 'cut', itemData)
      }
    },
    {
      label: '粘贴',
      accelerator: 'CmdOrCtrl+V',
      click: () => {
        event.sender.send('contextmenus:note:dirs', 'paste', itemData)
      }
    },
    {
      label: '复制路径',
      submenu: [
        {
          label: '文件名称（' + itemData.item.title + '）',
          click: () => {
            clipboard.writeText(itemData.item.title)
          }
        },
        {
          label: '绝对路径（' + join(notebookPath, itemData.item.relativePath) + '）',
          click: () => {
            clipboard.writeText(join(notebookPath, itemData.item.relativePath))
          }
        },
        {
          label: '相对路径（' + itemData.item.relativePath + '）',
          click: () => {
            clipboard.writeText(itemData.item.relativePath)
          }
        }
      ]
    },
    {type: 'separator'},
    {
      label: '删除',
      accelerator: 'Delete',
      click: () => {
        event.sender.send('contextmenus:note:dirs', 'delete', itemData)
      }
    },
    {type: 'separator'},
    {
      label: '重命名',
      accelerator: 'F2',
      click: () => {
        event.sender.send('contextmenus:note:dirs', 'rename', itemData)
      }
    }
  ])
  menu.popup({window: BrowserWindow.fromWebContents(event.sender) as BrowserWindow})
})
ipcMain.handle('contextmenus:note:files', async (event, item: DirectoryTreeNode) => {
  const itemData = JSON.parse(JSON.stringify(item)) as DirectoryTreeNode
  const notebookPath = await settingsDB.getSettings(['editor', 'notebookPath'])
  const menu = Menu.buildFromTemplate([
    {
      label: '新建文件',
      click: () => {
        event.sender.send('contextmenus:note:files', 'new-file', itemData)
      }
    },
    {type: 'separator'},
    {
      label: '打开文件所在位置',
      click: () => {
        shell.showItemInFolder(join(notebookPath, itemData.item.relativePath))
      }
    },
    {type: 'separator'},
    {
      label: '复制',
      accelerator: 'CmdOrCtrl+C',
      click: () => {
        event.sender.send('contextmenus:note:files', 'copy', itemData)
      }
    },
    {
      label: '剪切',
      accelerator: 'CmdOrCtrl+X',
      click: () => {
        event.sender.send('contextmenus:note:files', 'cut', itemData)
      }
    },
    {
      label: '粘贴',
      accelerator: 'CmdOrCtrl+V',
      click: () => {
        event.sender.send('contextmenus:note:files', 'paste', itemData)
      }
    },
    {
      label: '复制路径',
      submenu: [
        {
          label: '文件名称（' + itemData.item.title + '）',
          click: () => {
            clipboard.writeText(itemData.item.title)
          }
        },
        {
          label: '绝对路径（' + join(notebookPath, itemData.item.relativePath) + '）',
          click: () => {
            clipboard.writeText(join(notebookPath, itemData.item.relativePath))
          }
        },
        {
          label: '相对路径（' + itemData.item.relativePath + '）',
          click: () => {
            clipboard.writeText(itemData.item.relativePath)
          }
        }
      ]
    },
    {type: 'separator'},
    {
      label: '删除',
      accelerator: 'Delete',
      click: () => {
        event.sender.send('contextmenus:note:files', 'delete', itemData)
      }
    },
    {type: 'separator'},
    {
      label: '重命名',
      accelerator: 'F2',
      click: () => {
        event.sender.send('contextmenus:note:files', 'rename', itemData)
      }
    }
  ])
  menu.popup({window: BrowserWindow.fromWebContents(event.sender) as BrowserWindow})
})
